import Nifi from "src/nifi";
import type { Cell } from "pack-antv-x6"
import { h, computed } from "vue"
import markup from "./markup"
// import InfoElem from "./info.vue"
import ContextmenuElem from "./contextmenu.vue"
// import { IPackNifi } from "src/inter";
// import {get,set} from "lodash-es"
import { pickData, diff } from "../../util"

import FormElem from "./form.vue"
import { DEFAULT_NODE_PORTS, DEFAULT_CELL_NAME } from "../metadata";
import { ElMessage } from "element-plus";
import { has } from "lodash-es";
import {useThrottleFn } from "@vueuse/core"
//
import useProcessor from "../../processors";
import {t} from "../../i18n/index"


type CellState = "RUN_ONCE" | "STOPPED" | "RUNNING" | "DISABLED";
const KEYS: [key: string, sk?: any][] = [
    ['id'],
    ['type', 'component.type'],
    ['label', 'component.name'],
    ['status', 'status.runStatus'],
    ["position.x", "position.x"],
    ["position.y", "position.y"],
    ['version', 'revision.version'],
    ['info.input',"status.aggregateSnapshot.input"],
    ['info.output',"status.aggregateSnapshot.output"],
    ['info.read',"status.aggregateSnapshot.read"],
    ['info.written',"status.aggregateSnapshot.written"],
    ['info.tasks',"status.aggregateSnapshot.tasks"],
    ['info.tasksDuration',"status.aggregateSnapshot.tasksDuration"],
    ['invalid',(d:any) => (d.component.validationErrors || []).join('\n')],
];
const NKEYS: [key: string, sk?: any][] = [
    ["icon"],
    ["ports.items.0.id", 'inputPort'],
    ["ports.items.1.id", 'outputPort'],
]
const MDKEYS: [key: string, sk?: any][] = [
    ['inputPort'],
    ['outputPort'],
    ['icon'],
    ['defaultRelations'],
    ['excludeKeys']
]


// const KEYS = {'id':'id','component.type':'type','component.name':"label",'status.runStatus':"status","position.x":"position.x","position.y":"position.y"};
// const NodeKeys = {"icon":"icon","inputPort":"ports.items.0.id","outputPort":"ports.items.1.id"}
const name = DEFAULT_CELL_NAME.processors.en;
const shape = `node-${name}`;
//
export default (nifi: Nifi) => {
    // 注册 节点
    nifi.graph.registerNode(shape, markup);

    //  初始化元素     const markup = {ports:{items:[{id:inputPort || 'in.0.1',group:'left'},{id:outputPort || 'out.0',group:'right'}]}};
    // nifi.graph.onMounted((graph) => {
    //     // const bh = nifi.graphBox?.offsetHeight || 0;
    //     // 注册事件
    //     // graph.on("node:info",({e,node}:{e:MouseEvent,node:Node}) => {
    //     //     if(!nifi.graphBox) return;
    //     //     e.stopPropagation();
    //     //     e.preventDefault();
    //     //     // console.log('.........',node,e)
    //     //     const p = nifi.graphXY(e);
    //     //     const s = `left:${p.x}px;bottom:${bh - p.y + 10}px;`
    //     //     const el = nifi.box.popver(h(InfoElem,{node,nifi}),{direction:"top",autoRemove:true,parent:nifi.graphBox})
    //     //     el.open(s);
    //     // })

    //     // graph.on("node:added", (arg) => {
    //     //     console.log('...................node-added')
    //     //     const { node } = arg;
    //     //     if (node.prop('name') != 'processors') { return; }
    //     //     const cv: any = nifi.graph?.findView(node)
    //     //     setTimeout(() => {
    //     //         console.log('================');
    //     //         (cv?.selectors?.status as Element)?.addEventListener('mouseenter', (e) => {
    //     //             console.log('........', e)
    //     //             e.stopPropagation();
    //     //             e.preventDefault();
    //     //             const p = nifi.graphXY(e as MouseEvent);
    //     //             console.log('..........', p)
    //     //         })
    //     //     }, 100)

    //     // })
    // })
    //
    // const nodeMetadata = computed(() => {
    //     const md = new Map();
    //     const list = nifi.nodelist;
    //     for(const d of list){

    //     }
    //     return new Map();
    // })
    // 初始化数据
    const init = (tds: any[] | any) => {
        const res: any[] = [];
        for (const td of new Array().concat(tds)) {
            if (!td) continue;
            nifi.cells.set(td)
            const md: any = { ...pickData(td, KEYS), name, shape, ports: { items: DEFAULT_NODE_PORTS.items } };
            const cd = getMetadata(md.type);
            if (cd != undefined && cd != undefined) {
                Object.assign(md, cd)
                pickData(cd, NKEYS, md)
            }
            res.push(md)
        }
        return res;
    }

    // 新增元素
    const add = async (d: any) => {
        console.log('==========',d)
        const type = d.type;
        const pd: any = nifi.flow.processorTypes.find((t: any) => t.type == type);
        //
        if (pd) {
            const data = { component:{bundle: pd.bundle, ...d}, disconnectedNodeAcknowledged: false, revision: { clientId: nifi.flow.clientId, version: 0 } }
            const td = await nifi.cells.addCell(name, data)
            if (td) {
                const mds = init(td);
                nifi.graph?.addNode(mds[0]);
            }
        }
        else {
            ElMessage.warning('没有找到该类型的节点，请确认算子类型数据是否正确' + type)
        }

    }

    // 刷新单个元素 对比 目标数据和本地数据，只做差异刷新
    const update = (td: any) => {
        const { revision, id } = td;
        const sd = nifi.cells.get(id);
        nifi.cells.set(td)
        // 获取目标数据和原始数据并比较值的变化，取变化的值的集合
        const props: any = diff(pickData(td, KEYS), pickData(sd, KEYS));
        if (sd && revision.version == sd.revision.version && props == undefined) {
            console.info('=========== 没有发现版本和数据变化 无需更新节点属性 ============',props)
            return false;
        }
        
        //
        // console.log('节点更新属性集合 ======> ',props)
        if (props && Object.keys(props).length > 0) {
            nifi.graph?.getCellById(id)?.prop(props);
        }
        // 更新节点对应边的状态
        if(has(props,'info')){
            nifi.cells.connections.updateData(id)
        }
        else if (has(props, 'status')) {
            nifi.cells.connections.updateStatus(id);
        }
        // 
        return true;
    }
    // 更新单个元素
    const refresh = useThrottleFn(async (cell: Cell) => {
        try {
            const res = await nifi.cells.getCell(cell);
            update(res);
            return true;
        } catch (error) {
            ElMessage.error("更新算子失败 :: " + error)
            console.error(error)
            return false;
        }
    },1000)

    const del = async (cell:Cell) => {
        const b = await nifi.cells.delCell(cell)
        if(b !== false){
            nifi.graph.removeCell(cell);
            nifi.cells.del(cell)
        }
    }
    const changeState = async (cell:Cell,state:CellState) => {
        try {
            const td = await nifi.api.put(`/nifi-api/${cell.prop('name')}/${cell.id}/run-status`, { revision: nifi.cells.getCellRevision(cell), state, disconnectedNodeAcknowledged: false })
            update(td);
        } catch (error) {
            ElMessage.error('' + error)
            console.error(error)
        }
    }
    // 自动刷新单个节点的数据的开关
    const togglePower = async (cell:Cell) => {
        // 获取当前开关状态
        let b = cell.prop('power')
        // 状态为 on 时，关闭开关，并停止刷新循环
        // 状态为 off 时 打开开关并开启自动刷新循环
        clearInterval(b)
        if(b > -1){
            b = -1;
        }
        else {
            b = setInterval(() => {
                // 更新节点数据
                refresh(cell)
            },5000)
            nifi.local.saveIntervalHandle(b);
        }
        cell.prop({power:b})
        // console.log('===>',b)
    }
    // 菜单 status: "RUN_ONCE" | "STOPPED" | "RUNNING" | "DISABLED"
    const runOnce = (cell: Cell) => { changeState(cell, 'RUN_ONCE')}
    const run = (cell: Cell) => { changeState(cell, 'RUNNING') }
    const stop = (cell: Cell) => { changeState(cell, 'STOPPED') }
    const disable = (cell: Cell) => { changeState(cell, 'DISABLED') }
    const enable = (cell: Cell) => { changeState(cell, 'STOPPED') }
    const copy = () => { }
    //
    const view = async (cell: Cell) => {
        nifi.drawer.open();
        await refresh(cell)
        const vnode:any = h(FormElem, { nifi, cell, disabled: true })
        nifi.drawer.set(vnode)
    }
    const edit = async (cell: Cell) => {
        // nifi.box.closeAll();
        nifi.drawer.open();
        await refresh(cell)
        const vnode:any = h(FormElem, { nifi, cell })
        nifi.drawer.set(vnode)
    }
    // 右键菜单
    const contextmenu = (cell: Cell,evt:MouseEvent) => {
        const vnode:any = h(ContextmenuElem, { cell, nifi })
        nifi.contextmenu.open(evt,vnode)
    };
    //
    const metadata = useProcessor(nifi);
    const getMetadata = (type: string) => {
        // const nd = nifi.nodeMetadata.get(type);
        const td = metadata.get(type) || {}
        const nd = nifi.nodelist.find((d: any) => d.type === type);
        //
        if (nd) {
            pickData(nd, MDKEYS, td)
        }
        // if(td){
        //     Object.assign(res,td)
        // }
        // if(nd){
        //     pickData(nd,NKEYS,res)
        // }
        return td
    }
    // 数据溯源
    const provance = (cell:Cell) => {
        const id = cell.id;
        nifi.Provenance.open(id);
    }

    return {
        name,
        init,
        refresh,
        update,
        add,
        del,
        //
        getMetadata,
        provance,
        //
        togglePower,
        //
        changeState,
        runOnce,
        run,
        stop,
        disable,
        enable,
        copy,
        view,
        edit,
        contextmenu,
    }

}